package com.googlecode.flex_solder.containers  {
  /**
   * $Id: NavPanel.as 25 2009-02-17 01:43:57Z fuller.sethm $
   * 
   */

  import flash.display.DisplayObject;
  import flash.events.Event;
  import flash.events.MouseEvent;

  import mx.core.Container;

  import mx.collections.ArrayCollection;
  import mx.events.IndexChangedEvent;
  import mx.events.FlexEvent;

  import mx.containers.Box;
  import mx.containers.BoxDirection;
  import mx.containers.ViewStack;

  import mx.events.ChildExistenceChangedEvent;

  import mx.core.UIComponent;

  import mx.controls.Text;

  public class NavPanel extends Box {
    private var _textArray:Array = new Array();
    private var _textWidth:Number;

    private var _selectedIndex:int = -1;

    private var _viewStack:ViewStack = null;

    protected var panelNavSelected:String = "panelNavTitleSelected";
    protected var panelNav:String = "panelNavHeaderTitle";
    protected var panelNavMouseOver:String = "panelNavTitleMOver";
    protected var mouseDownStyle:String = null;

    public function NavPanel() {
    }

    protected function setupViewStack():void {
      if (_viewStack) {
	_viewStack.removeEventListener(ChildExistenceChangedEvent.CHILD_ADD,
					viewStackChildAddHandler);

	_viewStack.removeEventListener(ChildExistenceChangedEvent.CHILD_REMOVE,
					viewStackChildRemoveHandler);

	_viewStack.removeEventListener(Event.CHANGE, changeHandler);

	_viewStack.removeEventListener(IndexChangedEvent.CHILD_INDEX_CHANGE, 
				       viewStackChildIndexChangeHandler);
      }

      _viewStack.addEventListener(ChildExistenceChangedEvent.CHILD_ADD,
				   viewStackChildAddHandler);

      _viewStack.addEventListener(ChildExistenceChangedEvent.CHILD_REMOVE,
				   viewStackChildRemoveHandler);

      _viewStack.addEventListener(Event.CHANGE, changeHandler);

      _viewStack.addEventListener(IndexChangedEvent.CHILD_INDEX_CHANGE,
				   viewStackChildIndexChangeHandler);

      _viewStack.addEventListener(FlexEvent.CREATION_COMPLETE, 
				  creationCompleteHandler);

    }

    protected function creationCompleteHandler(event:FlexEvent):void {
      selectInitialOption();
    }

    public function initNavPanel():void {

      for (var idx:int = 0; idx < _viewStack.numChildren; idx++) {
	var childContainer:Container = Container(_viewStack.getChildAt(idx));
	initViewStackChild(childContainer);

      }

    }

    private function 
      viewStackChildAddHandler(event:ChildExistenceChangedEvent):void {
      // Prevent infinite recursion; the call to createNavItem() below
      // can cause this handler to get invoked due to event bubbling,
      // such as when a TabBar is inside a TabNavigator.
      if (event.target == this) {
	return;
      }

      // Bail if this isn't a child of the target stack.
      if (event.relatedObject.parent != _viewStack) {
	return;
      }

      var newViewStackChild:Container = Container(event.relatedObject);

      initViewStackChild(newViewStackChild);

    }


    protected function initViewStackChild(newViewStackChild:Container):void {

      var item:Text = createNavItem(newViewStackChild.label);

      var index:int
	= newViewStackChild.parent.getChildIndex(DisplayObject(newViewStackChild));
      _textArray.push(item);

      //      setChildIndex(item, index);

      if (newViewStackChild.toolTip) {
	item.toolTip = newViewStackChild.toolTip;
	newViewStackChild.toolTip = null;
      }

      item.addEventListener(MouseEvent.MOUSE_OVER, optionMouseOver);
      item.addEventListener(MouseEvent.MOUSE_OUT, optionMouseOut);
//       item.addEventListener(MouseEvent.MOUSE_DOWN, optionMouseDown);
      newViewStackChild.addEventListener("labelChanged", labelChangedHandler);
//       newViewStackChild.addEventListener("iconChanged", iconChangedHandler);
//       newViewStackChild.addEventListener("enabledChanged", enabledChangedHandler);
//       newViewStackChild.addEventListener("toolTipChanged", toolTipChangedHandler);
	
      item.enabled = true; // enabled && newViewStackChild.enabled;
    }

    private function labelChangedHandler(event:Event):void {
      // Event.target is a child of the target view stack. Need to
      // convert to index
      var itemIndex:int =
	_viewStack.getChildIndex(DisplayObject(event.target));

      updateNavItemLabel(itemIndex, Container(event.target).label);
    }

    protected function updateNavItemLabel(index:int, label:String):void {
      // Override if your nav item doesn't derive from Button.
      var item:Text = Text(_textArray[index]);

      item.text = label;
    }

    private function changeHandler(event:Event):void {
      // Change events from text fields propagate, so we need to make sure
      // this event is coming from our dataProvider
      //        if (event.target == dataProvider)
      hiliteSelectedNavItem(Object(event.target).selectedIndex);
    }

    /**
     *  @private
     */
    private function viewStackChildIndexChangeHandler(event:IndexChangedEvent):void {
      // Prevent infinite recursion; the call to setChildIndex() below
      // can cause this handler to get invoked due to event bubbling,
      // such as when a TabBar is inside a TabNavigator.
      if (event.target == this)
	return;

      _selectedIndex = event.newIndex;

      resetNavItems();
    }

    private function viewStackChildRemoveHandler(event:ChildExistenceChangedEvent):void {
      // Prevent infinite recursion; the call to removeChildAt() below
      // can cause this handler to get invoked due to event bubbling,
      // such as when a TabBar is inside a TabNavigator.
      if (event.target == this)
	return;

      var viewStack:ViewStack = ViewStack(event.target);
      //      removeChildAt(viewStack.getChildIndex(event.relatedObject));
      var removedChildIndex:int 
	= viewStack.getChildIndex(event.relatedObject);

      removeNavChild(removedChildIndex);

      callLater(resetNavItems);
    
    }

    protected function createNavItem(label:String):Text {
      // Create the new Text label.

      var newText:Text = new Text();

      newText.styleName = panelNav;
         
      if (label && label.length > 0)
	newText.text = label;
      else
	newText.text = " ";

      newText.width = (!isNaN(_textWidth) ? _textWidth : this.width - 10);

      addChild(newText);

      newText.addEventListener(MouseEvent.CLICK, navItemClickHandler);

      return newText;
    }

    protected function navItemClickHandler(event:MouseEvent):void {
      var index:int = _textArray.indexOf(Text(event.currentTarget));

      if (_viewStack) {
	hiliteSelectedNavItem(index);
      }
        
      _selectedIndex = index;
      trace('selectedIndex=' + _selectedIndex);

      _viewStack.selectedIndex = _selectedIndex;

    }

    protected function hiliteSelectedNavItem(index:int):void {
      var child:Text;
      // Un-hilite the current selection.
      if (_selectedIndex != index && _selectedIndex != -1
	  && _selectedIndex < _textArray.length) {
	child = Text(_textArray[_selectedIndex]);
	child.styleName = panelNav;
      }

      if (index < 0) {
	return;
      }

      // Hilite the new selection.
      child = Text(_textArray[index]);
      child.styleName = panelNavSelected;
      trace(child.text + ":" + child.styleName);
      //      child.enabled = false;
    }

    protected function resetNavItems():void {
      // Reset the index values and selection state.
      var len:int = _textArray.length;

      for (var idx:int = 0; idx < len; idx++) {
	var child:Text = Text(_textArray[idx]);
	child.enabled = !(idx == _selectedIndex);
      }

      invalidateDisplayList();
    }

    protected function removeNavChild(removedChildIndex:int):void {
      // Reset the index values and selection state.
      if (removedChildIndex == _selectedIndex) {
	_textArray.splice(removedChildIndex, 1);
	var textArrayLen:int = _textArray.length;
	if (textArrayLen > 0) {
	  _selectedIndex = (removedChildIndex + 1) % textArrayLen;
	}
	else {
	  _selectedIndex = -1;
	}
      }

    }

    protected function optionMouseOver(event:MouseEvent):void {
      Text(event.currentTarget).styleName = panelNavMouseOver;
    }

    protected function optionMouseOut(event:MouseEvent):void {
      var index:int = _textArray.indexOf(Text(event.currentTarget));

      if (index != _selectedIndex) {
	Text(event.currentTarget).styleName = panelNav;
      }
      else {
	Text(event.currentTarget).styleName = panelNavSelected;
      }
    }
	
    public function selectInitialOption():void {
      if (_viewStack && _viewStack.numChildren > 0) {
	Text(_textArray[0]).styleName = panelNavSelected;
	_selectedIndex = 0;
      }
    }

    public function get textWidth():Number {
      return _textWidth;
    }

    public function set textWidth(textWidth:Number):void {
      _textWidth = textWidth;
    }

    public function get viewStack():ViewStack {
      return _viewStack;
    }

    public function set viewStack(viewStack:ViewStack):void {
      _viewStack = viewStack;
      setupViewStack();

    }
  }
}